/**
* Form -
*
* Copyright (c) 2002
* Marty Phelan, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.taursys.xml;
import com.taursys.xml.render.*;
import com.taursys.xml.event.*;
import com.taursys.servlet.*;
import com.taursys.dom.*;
import java.util.*;
/**
* Form is ...
* @author Marty Phelan
* @version 1.0
*/
public class Form extends DocumentElement {
public static final String PARAMETER_MAP = "com.taursys.xml.ParameterMap";
private transient ArrayList initContextListeners;
private transient ArrayList initFormListeners;
private transient ArrayList openFormListeners;
private transient ArrayList closeFormListeners;
private InitContextDispatcher initContextDispatcher = new InitContextDispatcher(this);
private InitFormDispatcher initFormDispatcher = new InitFormDispatcher(this);
private OpenFormDispatcher openFormDispatcher = new OpenFormDispatcher(this);
private CloseFormDispatcher closeFormDispatcher = new CloseFormDispatcher(this);
private String sourceId;
private boolean initialized;
private DocumentAdapter documentAdapter;
private Map formContext = new HashMap();
// =======================================================================
// Constructors and Subcomponents
// =======================================================================
/**
* Constructs a new Form
*/
public Form() {
super();
addEventType(InitContextEvent.class.getName());
addEventType(InitFormEvent.class.getName());
addEventType(OpenFormEvent.class.getName());
addEventType(CloseFormEvent.class.getName());
addDispatcher(InitContextEvent.class.getName(), initContextDispatcher);
addDispatcher(InitFormEvent.class.getName(),initFormDispatcher);
addDispatcher(OpenFormEvent.class.getName(),openFormDispatcher);
addDispatcher(CloseFormEvent.class.getName(),closeFormDispatcher);
}
/**
* Creates the default DocumentElementRenderer for this component.
* By Default this methos returns a new DocumentElementRenderer.
* Override this method to define your own DocumentElementRenderer.
*/
protected DocumentElementRenderer createDefaultRenderer() {
return new FormRenderer(this);
}
// =======================================================================
// Event Initiator Methods
// =======================================================================
/**
* This method is invoked by run to dispatch the formContext to nested Forms.
* This method depends on the parameterMap property being set. A new context
* is constructed which contains everything already in this
* <code>Form's</code> plus the parameterMap.
*/
protected void dispatchInitContext() throws Exception {
HashMap newContext = new HashMap(formContext);
newContext.put(PARAMETER_MAP, getParameterMap());
initContextDispatcher.dispatch(newContext);
}
/**
* Initiate the dispatch of the <code>InitFormEvent</code> to registered
* nested <code>Forms</code>. This method should only be invoked after the
* <code>InitContextEvent</code> has been dispatched.
*/
protected void dispatchInitForm() throws Exception {
initFormDispatcher.dispatch();
}
/**
* Initiate the dispatch of the <code>OpenFormEvent</code> to registered
* nested <code>Forms</code>. This method should only be invoked after the
* <code>InitFormEvent</code> and <code>ParameterEvent</code> have been
* dispatched.
*/
protected void dispatchOpenForm() throws Exception {
openFormDispatcher.dispatch();
}
/**
* Initiate the dispatch of the <code>CloseFormEvent</code> to registered
* nested <code>Forms</code>. This method should be invoked after all
* processing is complete. Normally, nested <code>Forms</code> should be
* allowed to close before this form closes.
*/
protected void dispatchCloseForm() throws Exception {
closeFormDispatcher.dispatch();
}
// =======================================================================
// GENERAL EVENT PROCESSING
// =======================================================================
/**
* Processes given event by invoking the appropriate processX__Event method.
* The appropriate event type is determined by the class of the given
* EventObject.
*/
protected void processEvent(EventObject e) throws Exception {
if (e instanceof InitContextEvent)
processInitContextEvent((InitContextEvent)e);
if (e instanceof InitFormEvent)
processInitFormEvent((InitFormEvent)e);
if (e instanceof OpenFormEvent)
processOpenFormEvent((OpenFormEvent)e);
if (e instanceof CloseFormEvent)
processCloseFormEvent((CloseFormEvent)e);
else
super.processEvent(e);
}
// =======================================================================
// INIT CONTEXT EVENT METHODS
// =======================================================================
/**
* Processes a given InitContextEvent by setting the <code>formContext</code>
* and <code>parameterMap</code> from the given message, then dispatching an
* <code>InitContextEvent</code> to the <code>Form's</code> children, and
* finally propagating the <code>InitContextEvent</code> to registered
* listeners.
* @param e the InitContextEvent to process
*/
protected void processInitContextEvent(InitContextEvent e) throws Exception {
formContext = e.getContext();
setParameterMap((Map)lookup(PARAMETER_MAP));
initContextDispatcher.dispatch(e);
fireInitContextReceived(e);
}
/**
* Removes given listener from notification list for InitContextEvents
*/
public void removeInitContextListener(InitContextListener l) {
if (initContextListeners != null && initContextListeners.contains(l)) {
initContextListeners.remove(l);
}
}
/**
* Adds given listener to notification list for InitContextEvents
*/
public void addInitContextListener(InitContextListener l) {
if (initContextListeners != null) {
if (!initContextListeners.contains(l)) {
initContextListeners.add(l);
}
} else {
initContextListeners = new ArrayList();
initContextListeners.add(l);
}
}
/**
* Notifies all registered listeners of a given InitContextEvent
*/
protected void fireInitContextReceived(InitContextEvent e) throws Exception {
if (initContextListeners != null) {
Iterator iter = initContextListeners.iterator();
while (iter.hasNext()) {
((InitContextListener)iter.next()).initContext(e);
}
}
}
// =======================================================================
// INIT FORM EVENT METHODS
// =======================================================================
/**
* This method is invoked by run to initialize the form. It is
* the first method invoked by the doGet method before any parameters have
* been dispatched. This method sets the initialized flag to true.
* Override this method to provide custom behavior. If you override,
* be sure to invoke super.initForm or setInitialized(true) if this
* method should only be called once.
*/
protected void initForm() throws Exception {
initialized = true;
}
/**
* Processes a given InitFormEvent by invoking the Form's
* initForm method (unless initialized is true), then dispatching an
* <code>InitFormEvent</code> to the <code>Form's</code> children, and
* finally propagating the <code>InitFormEvent</code> to registered listeners.
* @param e the InitFormEvent to process
*/
protected void processInitFormEvent(InitFormEvent e) throws Exception {
if (!initialized)
initForm();
initFormDispatcher.dispatch(e);
fireInitFormReceived(e);
}
/**
* Removes given listener from notification list for InitFormEvents
*/
public void removeInitFormListener(InitFormListener l) {
if (initFormListeners != null && initFormListeners.contains(l)) {
initFormListeners.remove(l);
}
}
/**
* Adds given listener to notification list for InitFormEvents
*/
public void addInitFormListener(InitFormListener l) {
if (initFormListeners != null) {
if (!initFormListeners.contains(l)) {
initFormListeners.add(l);
}
} else {
initFormListeners = new ArrayList();
initFormListeners.add(l);
}
}
/**
* Notifies all registered listeners of a given InitFormEvent
*/
protected void fireInitFormReceived(InitFormEvent e) throws Exception {
if (initFormListeners != null) {
Iterator iter = initFormListeners.iterator();
while (iter.hasNext()) {
((InitFormListener)iter.next()).initForm(e);
}
}
}
// =======================================================================
// OPEN FORM EVENT METHODS
// =======================================================================
/**
* This method is invoked as part of the processOpenFormEvent method.
* It is normally invoked after processParameterEvent, but before
* processInputEvent. Override this method to provide custom
* behavior such as opening data sources. This implementation has no
* specific behavior.
*/
protected void openForm() throws Exception {
}
/**
* Processes a given OpenFormEvent by invoking the Form's
* openForm method, then dispatching an <code>OpenFormEvent</code> to the
* <code>Form's</code> children, and finally propagating the
* <code>OpenFormEvent</code> to registered listeners.
* @param e the OpenFormEvent to process
*/
protected void processOpenFormEvent(OpenFormEvent e) throws Exception {
openForm();
openFormDispatcher.dispatch(e);
fireOpenFormReceived(e);
}
/**
* Removes given listener from notification list for OpenFormEvents
*/
public void removeOpenFormListener(OpenFormListener l) {
if (openFormListeners != null && openFormListeners.contains(l)) {
openFormListeners.remove(l);
}
}
/**
* Adds given listener to notification list for OpenFormEvents
*/
public void addOpenFormListener(OpenFormListener l) {
if (openFormListeners != null) {
if (!openFormListeners.contains(l)) {
openFormListeners.add(l);
}
} else {
openFormListeners = new ArrayList();
openFormListeners.add(l);
}
}
/**
* Notifies all registered listeners of a given OpenFormEvent
*/
protected void fireOpenFormReceived(OpenFormEvent e) throws Exception {
if (openFormListeners != null) {
Iterator iter = openFormListeners.iterator();
while (iter.hasNext()) {
((OpenFormListener)iter.next()).openForm(e);
}
}
}
// =======================================================================
// CLOSE FORM EVENT METHODS
// =======================================================================
/**
* Closes the form and any resources it may have opened. This method is
* invoked by the processCloseForm method which is normally invoked at the
* end of the processing cycle but before this Form is recycled.
* Override this method to provide custom behavior. This implementation has
* no specific behavior.
*/
protected void closeForm() throws Exception {
}
/**
* Processes a given CloseFormEvent by invoking the Form's
* closeForm method, then dispatching an <code>CloseFormEvent</code> to the
* <code>Form's</code> children, and finally propagating the
* <code>CloseFormEvent</code> to registered listeners.
* @param e the CloseFormEvent to process
*/
protected void processCloseFormEvent(CloseFormEvent e) throws Exception {
closeForm();
closeFormDispatcher.dispatch(e);
fireCloseFormReceived(e);
}
/**
* Removes given listener from notification list for CloseFormEvents
*/
public void removeCloseFormListener(CloseFormListener l) {
if (closeFormListeners != null && closeFormListeners.contains(l)) {
closeFormListeners.remove(l);
}
}
/**
* Adds given listener to notification list for CloseFormEvents
*/
public void addCloseFormListener(CloseFormListener l) {
if (closeFormListeners != null) {
if (!closeFormListeners.contains(l)) {
closeFormListeners.add(l);
}
} else {
closeFormListeners = new ArrayList();
closeFormListeners.add(l);
}
}
/**
* Notifies all registered listeners of a given CloseFormEvent
*/
protected void fireCloseFormReceived(CloseFormEvent e) throws Exception {
if (closeFormListeners != null) {
Iterator iter = closeFormListeners.iterator();
while (iter.hasNext()) {
((CloseFormListener)iter.next()).closeForm(e);
}
}
}
// =======================================================================
// Property Accessors
// =======================================================================
/**
* Returns the id of the node this component is bound to. This is the node
* which this component will replicate.
*/
public String getSourceId() {
return sourceId;
}
/**
* Sets the id of the node this component is bound to. This is the node
* which this component will replicate.
*/
public void setSourceId(String sourceId) {
this.sourceId = sourceId;
}
/**
* Sets the document and creates the documentAdapter for this form.
* This is the document which will be typically be modified and sent
* back as the response.
* @param newDocument for this form.
*/
public void setDocument(org.w3c.dom.Document newDocument) {
/** @todo Use a factory to obtain a DocumentAdapter */
documentAdapter = new DOM_1_20000929_DocumentAdapter(newDocument);
}
/**
* Returns the document for this form. This is the document which will
* be sent back as the response. This is also the document which the
* components of this form will modify.
*/
public org.w3c.dom.Document getDocument() {
if (documentAdapter == null)
return null;
else
return documentAdapter.getDocument();
}
/**
* Sets the documentAdapter for this form. The document adapter is used
* by components as an adapter for the actual Document. The adapter provides
* the needed methods for components to manipulate the Document regardless
* of the DOM version.
* @param newDocumentAdapter for this form.
*/
public void setDocumentAdapter(DocumentAdapter newDocumentAdapter) {
documentAdapter = newDocumentAdapter;
}
/**
* Gets the documentAdapter for this form. The document adapter is used
* by components as an adapter for the actual Document. The adapter provides
* the needed methods for components to manipulate the Document regardless
* of the DOM version.
* @return the documentAdapter for this form.
*/
public DocumentAdapter getDocumentAdapter() {
return documentAdapter;
}
/**
* Sets an indicator that the form has been initialized (via the initForm method).
* The run method will only invoke the initForm method if this indicator is
* false, and then it will set this indicator to true. This will prevent the
* form from being initialized again (if it is recycled).
*/
public void setInitialized(boolean newInitialized) {
initialized = newInitialized;
}
/**
* Indicates whether the form has been initialized (via the initForm method).
* The run method will only invoke the initForm method if this indicator is
* false, and then it will set this indicator to true. This will prevent the
* form from being initialized again (if it is recycled).
*/
public boolean isInitialized() {
return initialized;
}
/**
* Get the <code>Map</code> of key/value pairs for this <code>Form's</code>
* context.
* @return the <code>Map</code> of key/value pairs for this <code>Form's</code>
* context.
*/
public Map getFormContext() {
return formContext;
}
/**
* Set the <code>Map</code> of key/value pairs for this <code>Form's</code>
* context.
* @param formContext the <code>Map</code> of key/value pairs for this
* <code>Form's</code> context.
* @throws IllegalArgumentException if the given value is null
*/
public void setFormContext(Map formContext) {
if (formContext == null)
throw new IllegalArgumentException("Attempt to set formContext to null");
this.formContext = formContext;
}
/**
* Lookup a value from this <code>Form's</code> context.
* @param key the key for the value to lookup
* @return the value as an Object or null if not found.
*/
public Object lookup(Object key) {
return formContext.get(key);
}
}